# Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
# This source file is part of the Cangjie project, licensed under Apache-2.0
# with Runtime Library Exception.
#
# See https://cangjie-lang.cn/pages/LICENSE for license information.

from os import path

types = ['Int8', 'Int16', 'Int32', 'Int64', 'UInt8', 'UInt16', 'UInt32', 'UInt64']
type_info = { ty : {} for ty in types }
for ty in types:
  ti = type_info[ty]
  ti['bits'] = int(ty[ty.index('t')+1:])
  ti['signed'] = ty[0] is not 'U'
  ti['expr'] = 'wrapped, {}(a, b)' if ti['bits'] is 64 \
    else '0, sub({{}}({ty}(a), {ty}(b)), {ty}(wrapped)) % {}'.format(2**ti['bits'], ty='Int64' if ti['signed'] else 'UInt64')
operator_info = {
  '+' : 'add',
  '-' : 'sub',
  '*' : 'mul'
}
path = path.dirname(path.realpath(__file__)) + '/test_a67_{}.cj'
template = '''
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
 * This source file is part of the Cangjie project, licensed under Apache-2.0
 * with Runtime Library Exception.
 *
 * See https://cangjie-lang.cn/pages/LICENSE for license information.
 */

/*
  @Assertion:   4.15(67) @OverflowWrapping If overflow occurs, wrapping around at the numeric bounds of the type,
                instead of throwing exception
  @Description: Checks for {ty} a, b that if a {op} b overflows in a function marked by @OverflowWrapping, the
                exception will not be thrown and the operation will be calculated by wrapping around at the numeric
                bounds.
  @Mode: run
  @Negative: no
  @Structure: complex-main
  @Dependencies: aux_a67.cj
  @CompileWarning: no
  @Comment: Auto-generated by gen.py
*/

from utils import utils.assert.Assert
from std import random.Random

func f(a: {ty}, b: {ty}) {{
    a {op} b
}}

@OverflowWrapping
func g(a: {ty}, b: {ty}) {{
    a {op} b
}}

main() {{
    let rnd = Random(123)
    var overflowCount : Int32 = 0

    do {{
        let a = rnd.next{ty}()
        let b = rnd.next{ty}()
        try {{
            f(a, b)
        }} catch (e: ArithmeticException) {{
            overflowCount++
            let wrapped = g(a, b)
            Assert.equals({})
        }}
    }} while (overflowCount < 256)
}}
'''
counter = 0

for ty in types:
  ti = type_info[ty]
  for op, op_info in operator_info.items():
    content = template.format(ti['expr'].format(op_info), ty=ty, op=op)
    counter += 1
    with open(path.format(str(counter).zfill(2)), 'w') as file:
      file.write(content)
       